package com.fly.base.util;


import lombok.Data;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 图表数据工具类
 */
public class ChartUtils {

    /**
     * 获取完整的的时间间隔列表
     *
     * @param startDate 开始时间
     * @param endDate   截止时间
     * @param dateType  时间类型（年、月、日）
     * @return 间隔的日期列表
     */
    public static List<LocalDate> getDateRange(LocalDate startDate, LocalDate endDate, ChronoUnit dateType) {
        // 时间间隔
        long dateBetween;
        UnaryOperator<LocalDate> dateAddFunction;
        switch (dateType) {
            case DAYS:
                dateBetween = ChronoUnit.DAYS.between(startDate, endDate);
                dateAddFunction = d -> d.plusDays(1);
                break;
            case WEEKS:
                dateBetween = ChronoUnit.WEEKS.between(startDate, endDate);
                dateAddFunction = d -> d.plusWeeks(1);
                break;
            case MONTHS:
                dateBetween = ChronoUnit.MONTHS.between(startDate, endDate);
                dateAddFunction = d -> d.plusMonths(1);
                break;
            case YEARS:
                dateBetween = ChronoUnit.YEARS.between(startDate, endDate);
                dateAddFunction = d -> d.plusYears(1);
                break;
            default:
                return Collections.emptyList();
        }

        if (dateBetween < 1) {
            // 开始时间>=截止时间
            return Collections.emptyList();
        }

        // 创建一个从开始时间、每次加一个单位时间的无限流，限制到截止时间为止
        List<LocalDate> dateList = Stream.iterate(startDate, dateAddFunction)
                .limit(dateBetween + 1)
                .collect(Collectors.toList());
        return dateList;
    }

    /**
     * 使用示例
     */
    public static void main(String[] args) {
        // 查询条件：startDate（开始日期）、startDate（截止日期）
        LocalDate startDate = LocalDate.of(2021,11,1);
        LocalDate endDate = LocalDate.of(2022,3,1);
        // 模拟从库中查询的数据（未补全的列表）
        List<DailyDataChartVo> oldList = new ArrayList<>();
        oldList.add(new DailyDataChartVo(LocalDate.now(), BigDecimal.ONE));

        // 补全横坐标日期
        List<DailyDataChartVo> newList = new ArrayList<>();
        if (CollectionUtils.isEmpty(oldList)) {
            // list的空判断
        }
        // 完整的日期间隔列表
        List<LocalDate> completeDates = ChartUtils.getDateRange(startDate, endDate, ChronoUnit.MONTHS);
        // 将从库中查出的list映射为map，日期作为键，自己作为值
        Map<LocalDate, DailyDataChartVo> map = oldList.stream()
                .collect(Collectors.toMap(DailyDataChartVo::getDate, Function.identity()));
        // 遍历完整的日期间隔列表，填充缺失的日期
        completeDates.forEach(c -> {
            if (map.containsKey(c)) {
                newList.add(map.get(c));
            } else {
                //没有这一天的数据，默认补0
                newList.add(new DailyDataChartVo(c, BigDecimal.ZERO));
            }
        });

        oldList.forEach(System.out::println);
        System.out.println();
        newList.forEach(System.out::println);
    }


    /**
     * 图表中的坐标点类
     */
    @Data
    private static class DailyDataChartVo {

        private LocalDate date;

        private BigDecimal value;

        public DailyDataChartVo(LocalDate date, BigDecimal value) {
            this.date = date;
            this.value = value;
        }
    }
}
